#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <netinet/in.h>

#include "server_socket.c"

#define SERVERPORT 3333 //定义端口号
#define BACKLOG 10 //请求队列中允许的最大请求数
#define MAXDATASIZE 50 //数据长度

// 字母大小写转换
char process_char(char c) {
    if (c >= 'a' && c <= 'z') {
        return c - 32;
    } else if (c >= 'A' && c <= 'Z') {
        return c + 32;
    }
    return c;
}


int main() {
    struct sockaddr_in cs;
    int c_size, recvbytes, listen_socket_fd, client_fd, i; 
    char buf[MAXDATASIZE];

	listen_socket_fd = tcp_listen_socket(SERVERPORT);	
	// 设置监听 socket 的 IO 为非阻塞 IO
	fcntl(listen_socket_fd, F_SETFL, O_NONBLOCK);
	
	fd_set rfds, readmask;
	int retval, maxfd;
	
	FD_ZERO(&rfds);
    FD_SET(listen_socket_fd, &rfds);
	maxfd = listen_socket_fd;

	for (;;) {
		readmask = rfds;
        retval = select(maxfd + 1, &readmask, NULL, NULL, NULL);
		
		if (FD_ISSET(listen_socket_fd, &readmask)) {
			// 非阻塞 accept
    		if((client_fd = accept(listen_socket_fd, (struct sockaddr *) &cs, &c_size)) == -1) {
        		if (errno == EAGAIN) continue;
				perror("accept");
        		exit(1);
    		}
			
    		printf("accept success! fd = %d\n", client_fd);
			// 将当前连接进来的 socket 设置为非阻塞
			fcntl(client_fd, F_SETFL, O_NONBLOCK);
			FD_SET(client_fd, &rfds);
			if (client_fd > maxfd) maxfd = client_fd;    		
		}
		
		int fd;
		for (fd = 0; fd <= maxfd; fd++) {
			if (fd == listen_socket_fd) continue;

			if (FD_ISSET(fd, &readmask)) {
				// 读取客户端数据（非阻塞 I/O）
				if((recvbytes = read(fd, buf, MAXDATASIZE)) == -1) {
        			perror("read error");
        			exit(1);
    			}
			
				if (recvbytes == 0) {
					close(fd);
					continue;
				}		
			
				for (i = 0; i < recvbytes; i++) {
					buf[i] = process_char(buf[i]);
				}
			
				// 非阻塞写
				// bug：有可能发送缓冲区没有空闲地方，这样数据就写不出去了
				// 解决办法：先将要写的数据缓存在用户态缓冲区，
				// 然后使用 select 检测这个 socket 的可读事件
				write(fd, buf, recvbytes);

				// 清空 buf
				memset(buf, 0x00, sizeof(buf));
			}
		}
	}
	// 7. 关闭服务端 server socket
    close(listen_socket_fd);
}
